// controller_app.cpp
#include "controller.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector>

static void write_default_file(const std::string& path, const std::string& content) {
  std::ofstream ofs(path, std::ios::out | std::ios::trunc);
  ofs << content;
}

static bool file_exists(const std::string& path) {
  std::ifstream ifs(path);
  return (bool)ifs;
}

static void print_usage(const char* exe) {
  std::cout <<
    "Usage:\n"
    "  " << exe << " [--bind_ip <ip>] [--tau_ms <ms>] [--win_ms <ms>] [--listen_port <port>] [--init]\n"
    "\n"
    "Options:\n"
    "  --bind_ip       Local bind IP for UDP sockets (default: 0.0.0.0)\n"
    "  --tau_ms        Controller period in milliseconds (default: 200)\n"
    "  --win_ms        Receive window per round in ms (default: 50)\n"
    "  --listen_port   Enable passive responder on this UDP port (0=disabled, default: 9101)\n"
    "  --init          Create sample neighbors.json and kz.json in current directory\n"
    "\n"
    "Notes:\n"
    "  * neighbors.json must list peers' responder ports, e.g. 9102 on the other machine.\n"
    "  * kz.json must contain your controller TF coefficients: {\"num\":[...],\"den\":[...]}.\n";
}

int main(int argc, char** argv) {
  const char* bind_ip = "0.0.0.0";
  int tau_ms = 200;
  int win_ms = 50;
  uint16_t listen_port = 9101;
  bool do_init = false;

  for (int i = 1; i < argc; ++i) {
    if (!std::strcmp(argv[i], "--bind_ip") && i+1 < argc) {
      bind_ip = argv[++i];
    } else if (!std::strcmp(argv[i], "--tau_ms") && i+1 < argc) {
      tau_ms = std::atoi(argv[++i]);
    } else if (!std::strcmp(argv[i], "--win_ms") && i+1 < argc) {
      win_ms = std::atoi(argv[++i]);
    } else if (!std::strcmp(argv[i], "--listen_port") && i+1 < argc) {
      listen_port = static_cast<uint16_t>(std::atoi(argv[++i]));
    } else if (!std::strcmp(argv[i], "--init")) {
      do_init = true;
    } else if (!std::strcmp(argv[i], "-h") || !std::strcmp(argv[i], "--help")) {
      print_usage(argv[0]);
      return 0;
    } else {
      std::cerr << "Unknown option: " << argv[i] << "\n";
      print_usage(argv[0]);
      return 1;
    }
  }

  if (do_init) {
    if (!file_exists("neighbors.json")) {
      // 示例：把本机当 A：监听 9101；假设对端 B 监听 9102
      write_default_file("neighbors.json",
R"JSON({
  "neighbors": [
    { "ip": "127.0.0.1", "port": 9102 }
  ]
}
)JSON");
      std::cout << "[init] wrote neighbors.json\n";
    } else {
      std::cout << "[init] neighbors.json already exists, skip\n";
    }

    if (!file_exists("kz.json")) {
      // 一个非常简单的 P 控制器示例：u = 0.1 * e
      write_default_file("kz.json", R"JSON({ "num":[0.1], "den":[1.0], "gamma":1.0 })JSON");
      std::cout << "[init] wrote kz.json\n";
    } else {
      std::cout << "[init] kz.json already exists, skip\n";
    }
  }

  // 这里真正调用你的控制器
  std::vector<tsync::Neighbor> dummy; // run_controller 会自己从 neighbors.json 读取
  const uint32_t tau_ns = static_cast<uint32_t>( (long long)tau_ms * 1000000LL );

  std::cout << "[app] bind_ip=" << bind_ip
            << " tau_ms=" << tau_ms
            << " win_ms=" << win_ms
            << " listen_port=" << listen_port
            << "\n";

  try {
    // 同时启用：常驻被动回包 + 周期性主动对齐
    tsync::run_controller(dummy, tau_ns, bind_ip, win_ms, listen_port);
  } catch (const std::exception& e) {
    std::cerr << "[app] fatal: " << e.what() << "\n";
    return 2;
  }
  return 0;
}
